﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace Game_Engine
{
    public class Material
    {
        private Matrix world;
        private Light light;
        private Camera camera;
        private Color surfaceColor;
        private float sheen;
        private Texture2D texture;
        private int offset, tiling;
        private Effect effect_;
        private Boolean on;

        public Material(Matrix w, Camera cam, Light l, Color c,
                    float s, int o, int t, Effect e, Texture2D tex)
        {
            World = w;
            Light = l;
            Color = c;
            Camera = cam;
            Sheen = s;
            Offset = o;
            Tiling = t;
            effect_ = e;
            texture = tex;
            on = true;
        }

        public void EnableMaterial()
        {
            On = true;
            if(effect_ != null)
                if (effect_.GetType() != typeof(BasicEffect))
                {
                    //The world transform of what we are trying to render. One good reason why
                    //we encapsulate these parameters: This is unique to every model/object
                    effect_.Parameters["World"].SetValue(World);
                    //View coordinates of the current camera
                    effect_.Parameters["View"].SetValue(Camera.View);
                    //Projection matrix of our camera
                    effect_.Parameters["Projection"].SetValue(Camera.Projection);
                    //World position of a light source
                    effect_.Parameters["LightPosition"].SetValue(Light.Transform.Position);
                    //World coordinates of the current camera
                    effect_.Parameters["CameraPosition"].SetValue(Camera.Transform.Position);
                    //Material shininess coefficient
                    effect_.Parameters["Sheen"].SetValue(Sheen);
                    //Texture to be applied
                    if (Texture != null)
                        effect_.Parameters["Texture"].SetValue(Texture);

                    effect_.Parameters["Tiling"].SetValue(Tiling);
                    effect_.Parameters["Offset"].SetValue(Offset);

                    effect_.Parameters["Diffuse"].SetValue(Color.ToVector3() * light.Diffuse.ToVector3());
                    effect_.Parameters["Specular"].SetValue(Color.ToVector3() * light.Specular.ToVector3());
                    effect_.Parameters["Ambient"].SetValue(Color.ToVector3() * light.Ambient.ToVector3());
                }
        }

        //Update all of the effect parameters -- meaning make all of their Properties
        //setable so we can handle camera/object/light movement in rendering
        public void Update(Matrix w, Camera cam, Light l, Color c, 
                            float s, int o, int t)
        {
            if (On)
            {
                World = w;
                Light = l;
                Color = c;
                Camera = cam;
                Sheen = s;
                Offset = o;
                Tiling = t;
                EnableMaterial();
            }
        }

        public Boolean On
        {
            get { return on; }
            set { on = value; }
        }

        public Matrix World
        {
            get {return world;}
            set { world = value; }
        }

        public Light Light
        {
            get {return light;}
            set { light = value; }
        }

        public Color Color
        {
            get { return surfaceColor; }
            set { surfaceColor = value; }
        }

        public Camera Camera
        {
            get {return camera;}
            set 
            { 
                camera = value;
            }
        }

        public float Sheen
        {
            get {return sheen;}
            set { sheen = value; }
        }

        public int Offset
        {
            get {return offset;}
            set { offset = value; }
        }

        public int Tiling
        {
            get { return tiling;}
            set { tiling = value; }
        }

        public Effect Effect
        {
            get { return effect_; }
        }

        public Texture2D Texture
        {
            get { return texture; }
        }
    }
}
